#pragma once
#include<iostream>
#include<functional>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/epoll.h>
#include<sys/eventfd.h>
#include<sys/timerfd.h>


class TimerTask
{
    using task = std::function<void()>;  //无参的回调，如果需要参数，有上层进行使用std::bind() 进行参数的绑定
    using releasetask = std::function<void(uint64_t)>;
private:
    uint64_t _id;
    uint64_t _delay;
    task _cb;
    releasetask _release;
    bool _is_canceled; //表示是否被取消
public:
    TimerTask(uint64_t id,uint64_t delay,task cb,releasetask rcb):_id(id),_delay(delay),_cb(cb),_release(rcb),_is_canceled(false){
        // std::cout<<"构造,id:"<<id<<"----addr:"<<this<<std::endl;
    } 
    ~TimerTask(){if(!_is_canceled)_cb();_release(_id);
        // std::cout<<"析构,id:"<<_id<<"----addr:"<<this<<std::endl;
    }  //_iscanceled 为false表示该任务未被取消，这时候执行任务回调
    uint64_t GetDelay(){return _delay;}      //获取定时任务设置的延时
    void CancelTask(){_is_canceled = true;}
};


class TimerWheel
{
    using task = std::function<void()>;
private:
    std::vector<std::vector<std::shared_ptr<TimerTask>>> _wheel;
    std::unordered_map<uint64_t,std::weak_ptr<TimerTask>> _tasks;
    int _timer_idx;
    int _timerfd;
    EventLoop* _loop;
    Channel* _timerfd_channel;  
#define MAXTIME 60
private:
    static int CreateTimerfd()
    {
        int timerfd = timerfd_create(CLOCK_MONOTONIC,TFD_CLOEXEC|TFD_NONBLOCK);
        assert(timerfd!=-1);
        struct itimerspec timeout;
        //第一次超时时间间隔
        timeout.it_value.tv_sec = 2;     // 第一次超时为 3 s
        timeout.it_value.tv_nsec = 0;
        //第二次以及之后的超时时间间隔
        timeout.it_interval.tv_sec = 1;  // 往后每隔 1s 超时一次
        timeout.it_interval.tv_nsec = 0;
        int ret = timerfd_settime(timerfd,0,&timeout,NULL);  //设置定时通知
        assert(ret!=-1);  //返回值为-1表示设置失败，但是一般是不会失败的，可以不用关心
        return timerfd;
    } 
    void AddTimerTaskInLoop(uint64_t id , uint64_t delay,task cb)
    {
        assert(_tasks.find(id) == _tasks.end());                   //确保 id 合法
        std::shared_ptr<TimerTask> pt(new TimerTask(id,delay,cb,std::bind(&TimerWheel::RealeaseTask ,this,std::placeholders::_1))); //构建任务对象
        std::weak_ptr<TimerTask> wpt(pt);                          //weak_ptr
        int pos = (_timer_idx + delay) % MAXTIME;                  //计算到期时间
        _wheel[pos].push_back(pt);                                 //定时任务放入时间轮
        _tasks[id] = wpt;                                          //添加到map中管理
    }
    //刷新/延迟定时任务
    void RefreshTimerTaskInLoop(uint64_t id)
    {
        std::unordered_map<uint64_t,std::weak_ptr<TimerTask>>::iterator it = _tasks.find(id);
        if(it==_tasks.end()) return;                          //id 不合法直接返回false
        std::shared_ptr<TimerTask> pt = it->second.lock();          //构造新的shared_ptr
        int pos = (_timer_idx + pt->GetDelay()) % MAXTIME;          //找到新的位置
        _wheel[pos].push_back(pt);
    }
    //取消定时任务
    void CancelTimerTaskInLoop(uint64_t id)
    {
        std::unordered_map<uint64_t,std::weak_ptr<TimerTask>>::iterator it = _tasks.find(id);
        if(it==_tasks.end()) return;
        (it->second).lock()->CancelTask();
    }
public:
    TimerWheel(EventLoop* loop):_wheel(MAXTIME),_timer_idx(0),_loop(loop),_timerfd(CreateTimerfd()),_timerfd_channel(new Channel(_timerfd,_loop))
    {
        _timerfd_channel->SetReadCallBack(std::bind(&TimerWheel::OnTime,this));
        _timerfd_channel->EnableRead();
    }
    ~TimerWheel(){delete _timerfd_channel;}
    void OnTime()
    {
        TimerRead();
        RunTick();
    }
    void TimerRead()
    {
        uint64_t val = 0;
        int ret = read(_timerfd,&val,sizeof val);
        if(ret<0)
        {
            if(errno == EAGAIN ||errno == EWOULDBLOCK ||errno == EINTR) return;
            ERROR_LOG("timerfd read failed");
            abort();
        }
        return;
    } 
    //添加定时任务
    bool AddTimerTask(uint64_t id , uint64_t delay,task cb);
    //刷新/延迟定时任务
    bool RefreshTimerTask(uint64_t id);
    //删除map的映射
    bool RealeaseTask(uint64_t id)
    {
        std::unordered_map<uint64_t,std::weak_ptr<TimerTask>>::iterator it = _tasks.find(id);
        if(it==_tasks.end()) return false;
        _tasks.erase(it);
        return true;
    }
    //取消定时任务
    bool CancelTimerTask(uint64_t id);
    //移动秒针
    void RunTick()
    {
        _timer_idx ++;
        _timer_idx %= MAXTIME; 
        // DEBUG_LOG("tick:%d",_timer_idx);
        _wheel[_timer_idx].clear();
    }
};

//添加定时任务
bool TimerWheel::AddTimerTask(uint64_t id , uint64_t delay,task cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::AddTimerTaskInLoop,this,id,delay,cb));
}
//刷新/延迟定时任务
bool TimerWheel::RefreshTimerTask(uint64_t id)
{
_loop->RunInLoop(std::bind(&TimerWheel::RefreshTimerTaskInLoop,this,id));
}
bool TimerWheel::CancelTimerTask(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::CancelTimerTaskInLoop,this,id));
}